package com.ecarx.vhaltests.e371.testcases.tcam;


import static com.ecarx.vhaltests.VhalUnitTestBase2.getIpcpClient;
import static com.ecarx.xui.adaptapi.car.vehicle.IVehicle.SETTING_FUNC_CAR_TCAM_LOCATOR_AUTH_CYCLE;
import static com.ecarx.xui.adaptapi.car.vehicle.IVehicle.SETTING_FUNC_CAR_TCAM_LOCATOR_UPDATE_AUTH_TIME;
import static com.ecarx.xui.adaptapi.car.vehicle.IVehicle.SETTING_FUNC_CAR_LOCATOR;

import android.car.VehicleAreaType;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.Log;

import androidx.test.platform.app.InstrumentationRegistry;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VehicleConstants;
import com.ecarx.vhaltests.VhalUnitTestBase;
import com.ecarx.xui.adaptapi.car.IWrapper;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

//[SW_FC_052_042]DCL功能授权时间开关。与DCL开关有联动关系
public class SettingFuncCarTcamLocatorAuthCycleTest extends VhalUnitTestBase {
    public static final String TAG = "TCAM_FUNC_LOCATOR_AUTH_CYCLE";

    private static final String VGM_GLB = "carTiGlb";
    private static final String VGM_YEAR = "tiAndDateIndcnYr1";
    private static final String VGM_MONTH = "tiAndDateIndcnMth1";
    private static final String VGM_DAY = "tiAndDateIndcnDay";
    private static final String VGM_HOUR = "tiAndDateIndcnHr1";
    private static final String VGM_MIN = "tiAndDateIndcnMins1";
    private static final String VGM_SEC = "tiAndDateIndcnSec1";

    private static final int TIME_THREE_MONTH = 1;
    private static final int TIME_SIX_MONTH = 2;
    private static final int TIME_YEAR = 3;

    private static IWrapper.IPropertyId cycleId;
    private static IWrapper.IPropertyId updateId;
    private static IWrapper.IPropertyId switchId;
    protected static IWrapper wrapper;
    private static int halValue;
    private static int halStatus;
    final static Object lock = new Object();
    private static final IpcpClient ipcpClient = new IpcpClient();


    @BeforeClass
    public static void testInit() {
        wrapper = com.ecarx.xui.adaptapi.car.Car.createWrapper(InstrumentationRegistry.getInstrumentation().getTargetContext());
        cycleId = wrapper.getWrappedPropertyId(IWrapper.WrappedIdType.ID_TYPE_FUNCTION, SETTING_FUNC_CAR_TCAM_LOCATOR_AUTH_CYCLE);
        updateId = wrapper.getWrappedPropertyId(IWrapper.WrappedIdType.ID_TYPE_FUNCTION, SETTING_FUNC_CAR_TCAM_LOCATOR_UPDATE_AUTH_TIME);
        switchId = wrapper.getWrappedPropertyId(IWrapper.WrappedIdType.ID_TYPE_FUNCTION, SETTING_FUNC_CAR_LOCATOR);
        mCarPropertyMgr.registerCallback(carPropertyEventCallback, cycleId.getPropertyId(), CarPropertyManager.SENSOR_RATE_ONCHANGE);
        setConfig();
    }

    @Test
    public void test01_tcamLocatorSwitchAvail() {
        setTestEnvironment(true);
        delay();
        settcamLocatorSwitch(true);
        lockWait();
        tcamLocatorAuthCycleTestAvail();
    }

    @Test
    public void test02_tcamLocatorSwitchAlwaysAvail() {
        setTestEnvironment(false);
        delay();
        lockWait();
        tcamLocatorAuthCycleTestAvail();
    }

    @Test
    public void test03_tcamLocatorAutoCycleAlwaysAvailBySwitch() {
        setTestEnvironment(true);
        delay();
        settcamLocatorSwitch(false);
        lockWait();
        tcamLocatorAuthCycleTestAvail();
    }

    @Test
    public void test04_TcamLocatorAuthCycleThreeMonth() {
        int carGlb = 20000;
        setTestEnvironment(true);
        delay();
        settcamLocatorSwitch(true);
        lockWait();
        setVGMValue(carGlb,23,3,15,10,0,0);
        lockWait();
        setTcamLocatorAuthCycle(TIME_THREE_MONTH);
        delay(500);
        setVGMValue(carGlb,23,6,16,10,0,0);
        lockWait();
        testTcamLocatorSwitch(false);
    }

    @Test
    public void test05_TcamLocatorAuthCycleSixMonth() {
        int carGlb = 20000;
        setTestEnvironment(true);
        delay();
        settcamLocatorSwitch(true);
        lockWait();
        setVGMValue(carGlb,23,3,15,10,0,0);
        lockWait();
        setTcamLocatorAuthCycle(TIME_SIX_MONTH);
        lockWait();
        setVGMValue(carGlb,23,9,16,10,0,0);
        lockWait();
        testTcamLocatorSwitch(false);
    }

    @Test
    public void test06_TcamLocatorAuthCycleYear() {
        int carGlb = 20000;
        setTestEnvironment(true);
        delay();
        settcamLocatorSwitch(true);
        lockWait();
        setVGMValue(carGlb,23,3,15,10,0,0);
        lockWait();
        setTcamLocatorAuthCycle(TIME_YEAR);
        delay(500);
        setVGMValue(carGlb,24,3,16,10,0,0);
        lockWait();
        testTcamLocatorSwitch(false);
    }

    private void setTcamLocatorAuthCycle(int value){
        mCarPropertyMgr.setIntProperty(cycleId.getPropertyId(),
                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, value);
    }

    private void testTcamLocatorSwitch(boolean value){
        boolean halValue = mCarPropertyMgr.getBooleanProperty(switchId.getPropertyId(), VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
        Assert.assertEquals(halValue, value);
    }

    private void settcamLocatorSwitch(boolean on){
        mCarPropertyMgr.setBooleanProperty(switchId.getPropertyId(),
                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, on);
    }
    
    private void tcamLocatorAuthCycleTestNotAvail(){
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(cycleId.getPropertyId(),
                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
        Assert.assertFalse(isAvail);
    }

    private void tcamLocatorAuthCycleTestAvail(){
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(cycleId.getPropertyId(),
                VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
        Assert.assertTrue(isAvail);
    }

    private static void setAvailable(boolean isAvail) {
        setAvailable(isAvail, true);
    }

    private static void setAvailable(boolean isAvail, boolean value) {
        int ccSvcId = 135;
        int[] ccOperIds = {200};

        int cemSvcId = 37;
        int[] cemOperIds = {999};
        int vgmSvcId = 49;
        int[] vgmOperIds = {999};

        ipcpClient.setConfig(ccSvcId, ccOperIds);
        ipcpClient.setConfig(cemSvcId, cemOperIds);
        ipcpClient.setConfig(vgmSvcId, vgmOperIds);

        int[] ccConfigs = {372};
        int[] ccValues = {2};
        boolean ccRet = ipcpClient.setCarconfigSignal(ccSvcId, ccOperIds[0], ccConfigs, ccValues);
        Assert.assertTrue(ccRet);

        String[] vgms = {"carLocatorSetResp" ,"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts"};
        int[] vgmValues = {value ? 1 : 0, isAvail ? VehicleConstants.CAR_MODE_NOMAL : VehicleConstants.CAR_MODE_TRANSPORT, VehicleConstants.USG_MODE_CONVENIENCE};
        boolean vgmResult = ipcpClient.setVGMSignal(vgmSvcId, vgmOperIds[0], vgms, vgmValues);
        Assert.assertTrue(vgmResult);
    }

    private static void setTestEnvironment(boolean flag) {
        setCarConfig(flag);
        //setVgm();
	    //setTimeoutValue(false);
        setAvailable(flag);
    }
    private static void setCarConfig( boolean isAvail) {
        int ccSvcId = 135;
        int ccOperIds = 200;
        int ccOperIdss[] = {ccOperIds};
        int[] configs = {220};
        int cc220 = isAvail? 10:2;
        int[] values = {cc220};

        ///ipcpClient.setConfig(ccSvcId, ccOperIdss);
        ipcpClient.setCarconfigSignal(ccSvcId, ccOperIds, configs, values);
        delay();
    }

    private void setVgm(){
        int vgmSvcId = 49;
        int[] vgmOperIds = {999};
        String[] vgms = {"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts","profPenSts1"};
        int[] vgmValues = {VehicleConstants.CAR_MODE_NOMAL, VehicleConstants.USG_MODE_ACTIVE, 3};
        boolean vgmResult = ipcpClient.setVGMSignal(vgmSvcId, vgmOperIds[0], vgms, vgmValues);
        delay();
        Assert.assertEquals(true, vgmResult);
    }

    private static void setConfig(){
        int ccSvcId = 135;
        int[] ccOperIds = {200};
        int vgmSvcId = 49;
        int[] vgmOperIds = {999};
        int timeoutSvcId = 99;
        int[] timeoutOperIds = {200};
        boolean vgmSet = ipcpClient.setConfig(vgmSvcId,vgmOperIds);
        Assert.assertEquals(true, vgmSet);
        boolean ccSet = ipcpClient.setConfig(ccSvcId, ccOperIds);
        Assert.assertEquals(true, ccSet);
        boolean timeOutSet = ipcpClient.setConfig(timeoutSvcId, timeoutOperIds);
        Assert.assertEquals(true, timeOutSet);
    }


    private static void setVGMValue(int glb, int year, int month, int day, int hour, int min, int sec) {
        int vgmSvcId = 49;
        int vgmOperId = 999;
	    String[] vgms = {VGM_GLB, VGM_YEAR, VGM_MONTH, VGM_DAY, VGM_HOUR, VGM_MIN, VGM_SEC,"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts","profPenSts1"};
        int[] vgmValues = {glb, year, month, day, hour, min, sec,VehicleConstants.CAR_MODE_NOMAL, VehicleConstants.USG_MODE_ACTIVE, 3};
        boolean vddmRet = ipcpClient.setVGMSignal(vgmSvcId, vgmOperId, vgms, vgmValues);
        Assert.assertTrue(vddmRet);
    }

    private void setTimeoutValue(boolean timeOut) {
        int timeoutSvcId = 99;
        int timeoutOperId = 200;
        String[] timeout = {"cpmOn1Timeout"};
        int[] timeoutValues = {timeOut ? 1 : 0};
        ipcpClient.setTimeoutSignal(timeoutSvcId, timeoutOperId, timeout, timeoutValues);
        delay();
    }

    private static final CarPropertyManager.CarPropertyEventCallback carPropertyEventCallback = new CarPropertyManager.CarPropertyEventCallback() {
        @Override
        public void onChangeEvent(CarPropertyValue carPropertyValue) {
            try {
                Log.d(TAG, "PasDclatAuthorizedTime onChangeEvent propertyId : " + carPropertyValue.getPropertyId() + " value is: " + carPropertyValue.getValue() + " Status is : " + carPropertyValue.getStatus());
                halValue = (int) carPropertyValue.getValue();
                synchronized (lock) {
                    lock.notify();
                }
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
        }

        @Override
        public void onErrorEvent(int i, int i1) {

        }
    };

    public void lockWait() {
        try {
            synchronized (lock) {
                lock.wait(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
